package com.mgq.java8.collector;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

/**
 * <b>功能：</b>自定义collector<br>
 *     java中实现toList(),和我们的类似 {@link java.util.stream.Collectors#toList()}
 *     return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
 *                                    (left, right) -> { left.addAll(right); return left; },
 *                                    CH_ID);
 * <b>Copyright mgq</b>
 * <li>版本&nbsp;&nbsp;&nbsp;&nbsp;修改日期&nbsp;&nbsp;&nbsp;&nbsp;部　　门&nbsp;&nbsp;&nbsp;&nbsp;作　者&nbsp;&nbsp;&nbsp;&nbsp;变更内容</li><hr>
 * <li>v1.0&nbsp;&nbsp;&nbsp;&nbsp;20220327&nbsp;&nbsp;营业后台&nbsp;&nbsp;&nbsp;&nbsp;马广奇&nbsp;&nbsp;&nbsp;&nbsp;创建类</li>
 * <br><br>
 *
 * @author 马广奇
 * @version 2022-03-27 20:23
 */
public class ToListCollector<T> implements Collector<T, List<T>, List<T>> {
    /**
     * 1.建立新的结果容器: supplier
     */
    @Override
    public Supplier<List<T>> supplier() {
        return ArrayList::new;
    }

    /**
     * 2.将元素添加到结果容器:accumulator
     */
    @Override
    public BiConsumer<List<T>, T> accumulator() {
        return List::add;
    }

    /**
     * 4.合并两个结果容器:combiner
     */
    @Override
    public BinaryOperator<List<T>> combiner() {
        return (list1, list2) -> {
            list1.addAll(list2);
            return list1;
        };
    }

    /**
     * 3.对结果容器应用最终转换 finisher
     */
    @Override
    public Function<List<T>, List<T>> finisher() {
        return Function.identity(); //表示输入什么就输出什么.不需要转换
    }

    /**
     * characteristics方法
     * UNORDERED:归约结果不受流中item的遍历和累计顺序的影响.
     * CONCURRENT: accumulator函数可以从多个线程同时调用,且改收集器可以并行归约流.如果收集器没有标位UNORDERED,那它仅在用于无序数据源时才可以并行归约
     * IDENTITY_FINISH: 表明完成器finisher方法返回的函数是一个恒等函数,可以跳过,这种情况下,累加器对象将会直接用作归约过程的最终结果.
     * 这也意味着,将累加器A不加检查地转换为结果R是安全的
     */
    @Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.CONCURRENT));
    }
}
